<?php
/**
 * Game_Building_Status
 *
 * Класс Game_Building_Status отвечает за обработку статусjd зданий
 *
 * @author Дмитрий Кузьма <kouzma.d@gmail.com>
 * @version 1.0
 */
class Game_Building_Status {
	
	private $_buildingId; // ID юнита
	private $_isBuilt; // флаг, исследован юнит или нет
	private $_isBuildingNow; // флаг, исследуется юнит в данный момент, или нет
	private $_arrBuildingsUnperformedDependences; // массив невыполненных зависимостей от зданий
	private $_objBuildingInfo; // объект с информацией о здании
	
	
	private static $_arrStatusesObjects; // Массив объектов с информацией о статусах в месте
	private static $_arrGameBuildingsDependecesByKeys; // Все возможные в игре зависимотси юнитов от зданий
	
	/**
	 * Создает новый объект статуса
	 * 
	 * @param int $buildingId
	 * @param bool $isBuilt
	 * @param bool $isBuildingNow
	 * @param Game_Building $objBuildingInfo
	 */
	private function __construct($buildingId, $isBuilt, $isBuildingNow, Game_Building $objBuildingInfo) {
		$this->_buildingId = $buildingId;
		$this->_isBuilt = $isBuilt;
		$this->_isBuildingNow = $isBuildingNow;
		$this->_objBuildingInfo = $objBuildingInfo;
	}
	
	/**
	 * Возвращает флаг, построено ли здание
	 */
	public function isBuilt() {
		return $this->_isBuilt;
	}
	
	/**
	 * Возвращает флаг, строится  ли здание в данный момент
	 */
	public function isBuildingNow() {
		return $this->_isBuildingNow;
	}
	
	/**
	 * Возвращает идентификатор юнита
	 */
	public function getBuildingId() {
		return $this->_buildingId;
	}

	
	/**
	 * Возвращает идентификатор юнита
	 */
	public function getBuildingsUnperformedDependences() {
		return $this->_arrBuildingsUnperformedDependences;
	}
	
	/**
	 * Возвращает идентификатор юнита
	 */
	public function getBuildingCreateInfo() {
		return $this->_objBuildingInfo;
	}
	
	/**
	 * Определяет, какие юниты, какой статус исследования/зависимостей от зданий имеют
	 */
	public static function getPlaceBuildingsStatuses() {
		if (!empty(self::$_arrStatusesObjects)) return self::$_arrStatusesObjects;
		$objGeneral = Game_General::instance();
		$arrBuildingsEvents = $objGeneral->objPlace->getBuildingsEvents();
		
		$arrAllBuildings = Game_Building::getAllBuildingsInfo();
		
		$arrBuildingsObjects = array();
		foreach ($arrAllBuildings as $arrBuilding) {
			$arrBuildingsObjects[$arrBuilding['ID_building']] = new Game_Building($arrBuilding);
		}
	
		// Определяем, что построено
		$arrBuiltBuildings = $objGeneral->objPlace->getBuildingsData();
		$arrBuiltBuildingsByKeys = array();
		foreach ($arrBuiltBuildings as $arrPlaceBuilding) {
			$buildingId = $arrPlaceBuilding['ID_building'];
			$arrBuiltBuildingsByKeys[$buildingId] = max(
					$arrPlaceBuilding['level'],
					empty($arrBuiltBuildingsByKeys[$buildingId]) ? 0 : $arrBuiltBuildingsByKeys[$buildingId]
			);
		}
		
		
		// Создаем объекты с информацией о статусах
		self::$_arrStatusesObjects = array();
		foreach ($arrBuildingsObjects as $buildingId => $objBuilding) {
			$isBuilt = false;
			if (isset($arrBuiltBuildingsByKeys[$buildingId])) $isBuilt = $arrBuiltBuildingsByKeys[$buildingId];
			self::$_arrStatusesObjects[$buildingId] = new Game_Building_Status($buildingId, $isBuilt, !empty($arrBuildingsEvents[$buildingId]), $objBuilding);
		}
		

	
		foreach (self::$_arrStatusesObjects as &$objBuildingStatus) {
			$objBuildingStatus->_fillDependences();
		}
		
		return self::$_arrStatusesObjects;
	}
	
	/**
	 * Заполняет зависимости от зданий
	 */
	private function _fillDependences() {
		$this->_arrBuildingsUnperformedDependences = array();
		$objGeneral = Game_General::instance();
		$arrPlaceBuildings = $objGeneral->objPlace->getBuildingsData();
		
		$arrStartDependences = $this->_getStartDependences();
		foreach ($arrStartDependences as $arrDependency) {
			$isNeed = true;
			foreach ($arrPlaceBuildings as $arrBuilding) {
				// Если построено необходимое здание
				if ($arrBuilding['ID_building'] == $arrDependency['ID_building_need']) {
					// Если уровень здания достаточен
					if ($arrBuilding['level'] >= $arrDependency['level']) {
						$isNeed = false;
						break;
					}
				}
			}
			if ($isNeed) $this->_arrBuildingsUnperformedDependences[] = $arrDependency;
		}
	}
	
	/**
	 * Возвращает все зависимости юнитов
	 *
	 * @return array:
	 */
	private static function _getBuildingsDependences() {
		if (!isset(self::$_arrGameBuildingsDependecesByKeys)) {
			$objDb = Service_Database::instance();
			$stmt = "
				SELECT *
				FROM `building_dependence`
			";
			$arrDependences = $objDb->select($stmt);
			 
			foreach ($arrDependences as $arrDependency) {
				$buildingId = $arrDependency['ID_building'];
				if (empty(self::$_arrGameBuildingsDependecesByKeys[$buildingId])) self::$_arrGameBuildingsDependecesByKeys[$buildingId] = array();
				self::$_arrGameBuildingsDependecesByKeys[$buildingId][] = $arrDependency;
			}
			 
		}
		return self::$_arrGameBuildingsDependecesByKeys;
	}
	
	/**
	 * Получает список зависимостей юнита
	 * 
	 * @return array
	 */
	private function _getStartDependences() {
		self::_getBuildingsDependences();
		if (empty(self::$_arrGameBuildingsDependecesByKeys[$this->getBuildingId()])) return array();
		return self::$_arrGameBuildingsDependecesByKeys[$this->getBuildingId()];
	}
	
	
	/**
	 * Возвращает статуст конкретного здания
	 * 
	 * @param int $buildingId
	 * @return Game_Building_Status:
	 */
	public static function getPlaceBuildingStatus($buildingId) {
		self::getPlaceBuildingsStatuses();
		if (empty(self::$_arrStatusesObjects[$buildingId])) return false;
		return self::$_arrStatusesObjects[$buildingId];
	}
	
	/**
	 * Метод осуществляет исследование юнита
	 *
	 * @throws Exception_Game 
	 */
	/*
	public function research() {
		// Проверяем, исследован ли он уже
		if ($this->isResearched()) throw new Exception_Game_Exist(Service_Translate::getText('Юнит уже исследован'));
		
		// Проверяем, не исследуется ли в данный момент
		if (Game_Event_Research::isPlaceEventExist($this->_unitId)) throw new Exception_Game_CurrentAction(Service_Translate::getText('Юнит в данный момент исследуется'));
		
		$objGeneral = Game_General::instance();
		// Проверяем, не исследуется ли в данный момент что-то другое в месте
		if ($objGeneral->objPlace->hasResearchEvents()) throw new Exception_Game_BusyWorkers(Service_Translate::getText('В данный момент проходят другие исследования'));
		
		// Проверяем, готовы ли все зависимости для иследования
		$arrBuildingsUnperformedDependences =  $this->getBuildingsUnperformedDependences();
		if (!empty($arrBuildingsUnperformedDependences)) throw new Exception_Game_BuildingsDependences();
		
		// Проверяем, достаточно ли ресурсов
		
		if (!$objGeneral->objPlace->objResourcesWithProduction->isEnoughResources($this->getResearchCost()->objResources)) {
			throw new Exception_Game_Resources();
		}
		
		return $this->_makeResearch();
	}*/
	/*
	private function _makeResearch() {
		// TODO по хорошему можно SQL транзакцию вставить, но не обязательно
		$objResourcesCost = $this->_objResearchCost->objResources;
		$objGeneral = Game_General::instance();
		$objGeneral->pay($objResourcesCost);
	
		$this->_createResearchEvent();
		return true;
	}
	*/
	
	/**
	 * Создает событие "Исследование юнита"
	 *
	 */
	/*
	private function _createResearchEvent() {
		$objGeneral = Game_General::instance();
		$objGameEvent = new Game_Event(array(
				'ID_place' => $objGeneral->objPlace->id,
				'ID_user' => $objGeneral->objUser->id,
				'event_type' => 'research',
				'ID_essence' => $this->_unitId,
				'amount' => 1,
				'event_time' => Service_Date::getTimestampToDBSaveWithSecondsMove($this->getResearchTime())
		));
		$objGameEvent->save();
	}*/
}
?>